/*
remote_cmd.c
offer remote server send command to terminal to control system
designed by lunanting

---------------------
2021-06-08 15:39:44
create file
---------------------
*/
#include "remote_cmd.h"
#include "stdio.h"
#include "cli_cmd.h"
#include "aos/kernel.h"
#include "mqtt.h"
#include "stdlib.h"

#define param_string(x) (#x)

static REMOTE *remote=NULL;

/*****************************************Need redefine *************************/
int xp_app_station_config(REMOTE *rm);
int xp_app_washer_config(REMOTE *rm);
int xp_app_dryer_config(REMOTE *rm);
/********************************************************************************/

int app_debug(char *type,char *fun,char *param);

static int xp_remoteCmd_station_config(void);
static int xp_remoteCmd_washer_config(void);
static int xp_remoteCmd_dryer_config(void);
static int xp_remoteCmd_tool_stringTO_coordinate(char *str,REMOTE_point *reback);
static void xp_remoteCmd_tool_stringTO_debug(const char *str,char *type,char *fun,char *param);
static int xp_remoteCmd_debug(char *type,char *fun,char *param);


static char debug_type[50]={0},debug_fun[50]={0},debug_param[50]={0};
static char debug_buf[100]={0};

/*
remote init
param:
    type: device tyoe , see DEVICE_type more
return:
    0=success
*/
int xp_remoteCmd_init(DEVICE_type type){
    if(type<=device_null||type>=device_max){
        perr("remote cmd init fail ! type= %d.",type);
        return -1;
    }
    remote=(REMOTE *)malloc(sizeof(REMOTE));
    if(remote== NULL){
        perr("remote cmd init fail ! malloc mem fail !");
        return -2;
    }
    memset(remote,0,sizeof(*remote));
    remote->type=type;
    if(type== device_station){
        if(xp_remoteCmd_station_config()!=0){
            perr("remote cmd config station api fail !");
            return -3;
        }
    }
    else if(type== device_washer){
        if(xp_remoteCmd_washer_config()!=0){
            perr("remote cmd config washer api fail !");
            return -4;
        }
    }
    else if(type== device_dryer){
        if(xp_remoteCmd_dryer_config()!=0){
            perr("remote cmd config dryer api fail !");
            return -5;
        }
    }
    else if(type== device_lite){

    }
    else if(type== device_swift){

    }
    xp_cli_debug_add(xp_remoteCmd_debug);
    remote->init=1;
    return 0;
}


/*
basic cmd deal
param:
    cmd: cmd string
    param: param string
return:
    1= matched
    0=no mateched
*/
static int remote_basic_cmd(const char *cmd,const char *param){
    int i=0;
    char buf[50]={0};
    char *p,*f;

    if(cmd==NULL){
        perr("basic cmd input error,cmd = NULL !");
        return 0;
    }
    strncpy(buf,param,49);
    p=strtok_r(buf,"\"",&f);
    if(p==NULL)return 0;
    if(strstr(cmd,"restart") != NULL){
        i=atoi(p);
        if(i == 1){
            println("system will restart ......");
            aos_reboot();
        }
    }
    else if(strstr(cmd,"product_key") != NULL){
        println("remote set product key: %s.",p);
        // aos_kv_set("product_key",param,strlen(param),1);
    }
    else if(strstr(cmd,"product_secret") != NULL){
        println("remote set product secret: %s.",p);
        // aos_kv_set("product_secret",param,strlen(param),1);
    }
    else if(strstr(cmd,"device_name") != NULL){
        println("remote set device name: %s.",p);
        // aos_kv_set("device_name",param,strlen(param),1);
    }
    else if(strstr(cmd,"device_secret") != NULL){
        println("remote set device secret: %s.",p);
        // aos_kv_set("device_secret",param,strlen(param),1);
    }
    else{
        return 0;
    }
    return 1;
}


/*
robot common cmd
param:
    cmd: cmd string
    param: param string
return:
    0= no matched
    1= matched
*/
static int xp_remoteCmd_robot_common(const char *cmd,const char *param){
    int i=0;
    float f=0.0;
    int regist=1;
    REMOTE_point point={0};
    char api_string[50];
    char p_str[50]={0};
    char *p,*ft;
    
    if(strstr(cmd,REMOTE_unemergency)!=NULL){
        i=atoi(param);
        if(remote->robot_common.unemergency!=NULL){
            if(i==1){
                remote->robot_common.unemergency();
                println_remote("recover ermergency !");
            }
        }
        else{
            strcpy(api_string,"recover emergency");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_auto_back)!=NULL){
        i=atoi(param);
        if(remote->robot_common.auto_back !=NULL){
            if(i==1){
                println_remote("start auto back !");
                if(remote->robot_common.auto_back()!=0){
                    perr_remote("start auto back fail !");
                }
            }
        }
        else{
            strcpy(api_string,"auto back");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_recover)!=NULL){
        i=atoi(param);
        if(remote->robot_common.recover!=NULL){
            if(i==1){
                println_remote("start recover strcture !");
                if(remote->robot_common.recover()!=0){
                    perr_remote("recover structure fail !");
                }
            }
        }
        else{
            strcpy(api_string,"recover structure");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_max_hight)!=NULL){
        f=atof(param);
        if(remote->robot_common.max_hight!=NULL){
            remote->robot_common.max_hight(f);
            println_remote("set max hight= %.2f",f);
        }
        else{
            strcpy(api_string,"set max hight");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_forward)!=NULL){
        f=atof(param);
        if(remote->robot_common.forward!=NULL){
            println_remote("agv forward:%.2f",f);
            if(remote->robot_common.forward(f)!=0){
                perr_remote("agv forward fail !");
            }
        }
        else{
            strcpy(api_string,"agv forwrd");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_back)!=NULL){
        f=atof(param);
        if(remote->robot_common.back!=NULL){
            println_remote("agv back: %.2s",f);
            if(remote->robot_common.back(f)!=0){
                perr_remote("agv back fail !");
            }
        }
        else{
            strcpy(api_string,"agv brack");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_left)!=NULL){
        i=atoi(param);
        if(remote->robot_common.left!=NULL){
            if(i==1){
                println_remote("start agv left !");
                if(remote->robot_common.left()!=0){
                    perr_remote("agv left fail !");
                }
            }
        }
        else{
            strcpy(api_string,"agv left");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_right)!=NULL){
        i=atoi(param);
        if(remote->robot_common.right!=NULL){
            if(i==1){
                println_remote("start agv right");
                if(remote->robot_common.right()!= NULL){
                    perr_remote("agv right fail !");
                }
            }
        }
        else{
            strcpy(api_string,"agv right");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_stop)!=NULL){
        i=atoi(param);
        if(remote->robot_common.stop!=NULL){
            if(i==1){
                println_remote("start agv stop !");
                if(remote->robot_common.stop()!=NULL){
                    perr_remote("agv stop fail !");
                }
            }
        }
        else{
            strcpy(api_string,"agv stop");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_lidar_blow)!=NULL){
        i=atoi(param);
        if(remote->robot_common.lidar_blow!=NULL){
            if(i==1){
                println_remote("start lidar blow !");
                remote->robot_common.lidar_blow();
            }
        }
        else{
            strcpy(api_string,"lidar blow");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_standby_point)!=NULL){
        strncpy(p_str,param,49);
        p=strtok_r(p_str,"\"",&ft);
        i=xp_remoteCmd_tool_stringTO_coordinate(p,&point);
        if(remote->robot_common.standby_point!=NULL){
            if(i==0){
                println_remote("set standby point: %s.",p);
                if(remote->robot_common.standby_point(point.x,point.y,point.angle)!=0){
                    perr_remote("set standby point fail .");
                }
            }
            else{
                perr_remote("set standby point fault: %s.",p);
            }
        }
        else{
            strcpy(api_string,"set standby point");
            regist=0;
        }
    }
    else if(strstr(cmd,REMOTE_goto_point)!=NULL){
        strncpy(p_str,param,49);
        p=strtok_r(p_str,"\"",&ft);
        i=xp_remoteCmd_tool_stringTO_coordinate(p,&point);
        if(remote->robot_common.goto_point!=NULL){
            if(i==0){
                println_remote("start goto point: %s.",p);
                if(remote->robot_common.goto_point(point.x,point.y,point.angle)!=0){
                    perr_remote("goto point fail.");
                }
            }
            else{
                perr_remote("set goto point fault:%s.",p);
            }
        }
        else{
            strcpy(api_string,"goto point");
            regist=0;
        }
    }

    else{
        return 0;
    }
    if(regist== 0){
        perr_remote("%s api no regist !",api_string);
    }
    
    return 1;
}



/*
station common cmd
param:
    cmd: cmd string
    param: param string
return:
    0= no matched
    1= matched
*/
static int xp_remoteCmd_station_common(const char *cmd,const char *param){
    int i=0;

    if(strstr(cmd,REMOTE_max_number)!=NULL){
        i=atoi(param);
        if(remote->station.set_robot_num!=NULL){
            println_remote("set robot num: %s.",param);
            if(remote->station.set_robot_num(i)!=0){
                perr_remote("set robot num fail .");
            }
        }
        else{
            perr_remote("set robot num api no regist !");
        }
    }
    else if(strstr(cmd,REMOTE_park_check)!=NULL){
        i=atoi(param);
        if(remote->station.park_check!=NULL){
            println_remote("set park check: %s.",param);
            remote->station.park_check(i);
        }
        else{
            perr_remote("set park check api no regist !");
        }
    }
    else if(strstr(cmd,REMOTE_auto_recover)!=NULL){
        i=atoi(param);
        if(remote->station.auto_recover!=NULL){
            println_remote("auto recover: %s.",param);
            remote->station.auto_recover(i);
        }
        else{
            perr_remote("set park check api no regist !");
        }
    }
    else{
        return 0;
    }
    return 1;
}



/*
washer cmd
param:
    cmd: cmd string
    param: param string
return:
    0= no matched 
    1= matched
*/
static int xp_remoteCmd_washer(const char *cmd,const char *param){
    int i=0;
    float f=0.0;

    if(strstr(cmd,REMOTE_lifter)!=NULL){
        f=atof(param);
        if(remote->washer.lifter!=NULL){
            println_remote("lifter move: %.3f.",f);
            if(remote->washer.lifter(f)!=0){
                perr_remote("lifter move fail !");
            }
        }
        else{
            perr_remote(" lifter move api no regist !");
        }
    }
    else if(strstr(cmd,REMOTE_turner)!=NULL){
        i=atoi(param);
        if(remote->washer.turner!=NULL){
            println_remote("turner move: %s.",param);
            if(remote->washer.turner(i)!=0){
                perr_remote("turner move fail !");
            }
        }
        else{
            perr_remote("turner move api no regist !");
        }
    }
    else if(strstr(cmd,REMOTE_putter)!=NULL){
        i=atoi(param);
        if(remote->washer.putter!=NULL){
            println_remote("putter move: %s.",param);
            if(remote->washer.putter(i)!=0){
                perr_remote("putter move fail !");
            }
        }
        else{
            perr_remote("putter move api no regist !");
        }
    }
    else if(strstr(cmd,REMOTE_brush)!=NULL){
        i=atoi(param);
        if(remote->washer.brush!=NULL){
            println_remote("brush run: %s.",param);
            if(remote->washer.brush(i)!=0){
                perr_remote("brush run fail !");
            }
        }
        else{
            perr_remote("brush run api no regist ");
        }
    }
    else{
        return 0;
    }
    return 1;
}



/*
dryer cmd
param:
    cmd: cmd string
    param: param string
return:
    0= no matched
    1= matched
*/
static int xp_remoteCmd_dryer(const char *cmd,const char *param){
    int i=0;
    float f=0.0;

    if(strstr(cmd,REMOTE_lifter)!=NULL){
        f=atof(param);
        if(remote->dryer.lifter!=NULL){
            println_remote("lifter move: %s.",param);
            if(remote->dryer.lifter(f)!=0){
                perr_remote("lifter move fail !");
            }
        }
        else{
            perr_remote("lifter move api no regist !");
        }
    }
    else if(strstr(cmd,REMOTE_swing)!=NULL){
        i=atoi(param);
        if(remote->dryer.swing!=NULL){
            println_remote("swing move: %s.",param);
            if(remote->dryer.swing(i)!=0){
                perr_remote("swing move fail !");
            }
        }
        else{
            perr_remote("swing move api no regist !");
        }
    }
    else if(strstr(cmd,REMOTE_dryer_blow)!=NULL){
        i=atoi(param);
        if(remote->dryer.dryer_blow!=NULL){
            println_remote("dryer blow run: %s.",param);
            if(remote->dryer.dryer_blow(i)!=0){
                perr_remote("dryer blow run fail !");
            }
        }
        else{
            perr_remote("dryer blow api no regist !");
        }
    }
    else{
        return 0;
    }
    return 1;
}


/*
config station api demo
return:
    0= success
*/
static int xp_remoteCmd_station_config(void){
    if(xp_app_station_config(remote)!=0){
        return -1;
    }
    return 0;
}

/*
config washer api demo
return:
    0= success
*/
static int xp_remoteCmd_washer_config(void){
    if(xp_app_washer_config(remote)!=0){
        return -1;
    }
    return 0;
}


/*
config dryer api demo
return:
    0=success
*/
static int xp_remoteCmd_dryer_config(void){
    if(xp_app_dryer_config(remote)!=0){
        return -1;
    }
    return 0;
}


/*
remote cmd deal
param:
    type: device type , see DEVICE_type more
    cmd: cmd string
    param: param string
return:
    0= no matched
    1= matched
*/
int xp_remoteCmd_deal(DEVICE_type type,const char *cmd,const char *param){
    int sta=0;

    if(remote_basic_cmd(cmd,param)){
        return 1;
    }
    if(remote==NULL||remote->init!=1){
        perr("remote cmd no init !");
        return 0;
    }
    if(strstr(cmd,"debug")!=NULL){
        xp_remoteCmd_tool_stringTO_debug(param,debug_type,debug_fun,debug_param);
        println("remote debug cmd: %s %s %s.",debug_type,debug_fun,debug_param);
        xp_cli_cmd_set(debug_type,debug_fun,debug_param);
        return 1;
    }
    switch(type){
        case device_station:
            if(xp_remoteCmd_station_common(cmd,param)){
                sta =1;
            }
            break;
        case device_washer:
            if(xp_remoteCmd_robot_common(cmd,param)){
                sta=1;
            }
            else if(xp_remoteCmd_washer(cmd,param)){
                sta =1;
            }
            else{
                sta =0;
            }
            break;
        case device_dryer:
            if(xp_remoteCmd_robot_common(cmd,param)){
                sta =1;
            }
            else if(xp_remoteCmd_dryer(cmd,param)){
                sta =1;
            }
            else{
                sta =0;
            }
            break;
        case device_lite:
            if(xp_remoteCmd_robot_common(cmd,param)){
                sta =1;
            }
            else{
                sta =0;
            }
            break;
        case device_swift:
            if(xp_remoteCmd_robot_common(cmd,param)){
                sta =1;
            }
            else{
                sta =0;
            }
            break;
        default:
            perr("device type unusable !");
            sta =0;
            break;
    }

    return sta;
}


/***********************weak define***************/
/*
以下函数需要在业务层重新定义和实现内容，
如果没有配置对应的端口，对应的接口功能就无效~
*/
__weak int xp_app_station_config(REMOTE *rm){
    #if 0   //e.g.
    rm->station.set_rebot_num=xp_robots_layout_set;
    rm->station.park_check=xp_station_net_parkCheck_set;
    #endif

    perr_remote("Need define station config api ,weak define now!");
    return 0;
}
__weak int xp_app_washer_config(REMOTE *rm){
    #if 0   //e.g.
    //common api
    rm->robot_common.unemergency=
    rm->robot_common.auto_back=
    rm->robot_common.recover=
    rm->robot_common.max_hight=
    rm->robot_common.forward=
    rm->robot_common.back=
    rm->robot_common.left=
    rm->robot_common.right=
    rm->robot_common.stop=
    rm->robot_common.lidar_blow=
    rm->robot_common.standby_point=
    rm->robot_common.goto_point=

    //washer api
    rm->washer.lifter=
    rm->washer.turner=
    rm->washer.putter=
    rm->washer.brush=
    #endif
    perr_remote("Need define washer config api ,weak define now!");
    return 0;
}
__weak int xp_app_dryer_config(REMOTE *rm){
    #if 0   //e.g.
    //common api
    rm->robot_common.unemergency=
    rm->robot_common.auto_back=
    rm->robot_common.recover=
    rm->robot_common.max_hight=
    rm->robot_common.forward=
    rm->robot_common.back=
    rm->robot_common.left=
    rm->robot_common.right=
    rm->robot_common.stop=
    rm->robot_common.lidar_blow=
    rm->robot_common.standby_point=
    rm->robot_common.goto_point=

    //dryer api
    rm->dryer.lifter=
    rm->dryer.swing=
    rm->dryer.dryer_blow=
    #endif
    perr_remote("Need define dryer config api ,weak define now!");
    return 0;
}


/*********************tool function*****************/
/*
string to point coordinate
param:
    str: coordinate string  format: "x&y&angle"
    reback: return REMOTE_point msg
return:
    0=success
*/
static int xp_remoteCmd_tool_stringTO_coordinate(char *str,REMOTE_point *reback){
    char buf[50]={0};
    char *p,*f;
    char split[]="&";
    REMOTE_point point;

    if(str==NULL)return -1;
    strncpy(buf,str,49);
    p=strtok_r(buf,split,&f);
    point.x=atoi(p);
    if(f==NULL)return -2;
    p=strtok_r(NULL,split,&f);
    point.y=atoi(p);
    if(f==NULL)return -3;
    point.angle=atof(f);
    *reback=point;
    return 0;
}


/*
change string to debug format string   ";" split
param:
    str: recive string
    type: save debug type string
    fun: save debug fun string
    param: save debug param string
*/
static void xp_remoteCmd_tool_stringTO_debug(const char *str,char *type,char *fun,char *param){
    char split[]="*";
    char *p,*f;

    if(str==NULL){
        return;
    }
    strncpy(debug_buf,str,99);
    p=strtok_r(debug_buf,"\"",&f);
    if(p==NULL)return;
    memset(type,0,49);
    memset(fun,0,49);
    memset(param,0,49);
    p=strtok_r(p,split,&f);
    if(p==NULL){
        return;
    }
    strncpy(type,p,49);
    p=strtok_r(NULL,split,&f);
    if(p==NULL){
        return;
    }
    strncpy(fun,p,49);
    p=strtok_r(NULL,split,&f);
    if(p==NULL){
        return;
    }
    strncpy(param,p,49);
}

/***************************************debug********************************/

/*
remote debug
*/
static int xp_remoteCmd_debug(char *type,char *fun,char *param){
    if(strcmp(type,"remote")!=0)return 0;
    if(xp_remoteCmd_deal(remote->type,fun,param)){}
    else{
        return 0;
    }
    return 1;
}



//end of the file
